Okay.
We're getting pretty close to the end of our project.
So in this lecture we're going to finish up scripting the story for our basement, where we're going
to listen for when the basement door is opened and when it is, we'll enable a prompt on the breaker
and wait for that prompt to get triggered.
Once that prompt is triggered, we'll restore the power in the basement and then start a countdown of
around 60s for the players to reach the exit door in the basement.
So after we have finished with our stair scene, the next thing we'll want to do is we're going to listen
inside of the workspace.
Inside of the Krusty Krab, we're going to look in the doors folder and get our locked door, and we're
going to get an attribute change signal, and we're going to wait for the locked attribute to change,
because this will change when that door gets unlocked.
So we're going to wait for this to happen.
So this will notify us when the players have gotten the key and then opened and unlocked the basement
breaker room door.
Once that happens, then we're going to reference in the workspace.
Krusty Krab basement.
We're going to get the breaker box, and inside of the body of the breaker box, there's an attachment
with our proximity prompt inside of it, and we're going to want to enable this prompt.
That way the players can activate it.
And then we're just going to copy this.
And we're going to wait for this prompt to get triggered.
Once this prompt is triggered, then we need to go ahead and restore the power in the basement so we
can go ahead and create a private function.
And I'm just going to call this function Restore power.
And what we're going to do is we're just going to call our change light's function and pass true.
And then we also need to play a sound as well.
So we're going to use the game comms event and fire to all the clients and use the game comms enum on
the client.
And two clients play sound, and the sound is going to be inside of the sound service ambience dot.
And it's called restored.
And we're going to set play at point equal to false.
So if I go down into the sound service we go into the ambience folder.
Here's the restored sound.
This is what we're going to play when we turn back on the power.
Pretty simple.
Once we have restored the power, the next thing we'll want to do is we're going to want to open the
door that leads to the exit inside of our basement.
So if we go all the way back here, this is the door right here that we're going to open to allow the
players to touch this escape part.
And we're also going to change this light up here to green.
So that means we're going to have to tween this door slowly open so we can go ahead and create a function.
And I'll just call this function something like enable exit door.
And we'll make a reference to the exit door inside of the workspace Krusty Krab basement and get the
exit door.
We're also going to refer to the escape part, which is in the workspace Krusty Krab basement escape
part.
And then we're going to make a reference to the light that's above the door as well.
We'll call it Escape Light, and that's in the workspace Krusty Krab basement exit door light.
And then from this point, inside of the escape part, we have a surface light in there, and we're
going to enable that surface light.
And I'll go ahead and show you what that does.
So when we rotate this door open, let me just change the rotation of the hinge here.
And we could do something like.
We'll just do that for now.
When the store opens, we want to have light glowing out and hitting this wall.
So inside of the escape part, there's a surface light.
And when we enable that, it's going to have this bright glowing light coming out of this doorway,
which looks kind of cool.
So let me go ahead and place this hinge back to its regular state.
So once we've enabled the surface light, then we're going to want to change the color of the bulb in
our escape light.
So escape light bulb, we want to set the color to be green.
So we could define a constant up here.
We'll just call this constant green.
And we'll make it equal to a color three dot from RGB.
And we'll just pass in some random green color like that.
We'll go back down and we'll set this equal to the green color.
And then we're also going to change the point light inside of the bulb as well.
So the light bulb will get the point light in there.
And we'll change the color of that as well equal to the green color.
And now we're going to use the game comms event and fire to all of the clients to play another sound.
So game comms enum client two client play sound.
And the sound that we want for them to play is going to be inside of our exit door.
We get the door and then there's a sound in there called alarm.
We're going to set play at point equal to true.
And the position for that is going to be equal to our exit door dot door dot position.
After that, we can go ahead and use the better tween service to go ahead and rotate the door so we
can go ahead and require it at the top here we'll get the better tween.
And will require inside of the server script service, dot server, dot modules, dot beta tween.
And then we can go back down and use the beta tween service and create a tween on our exit door hinge.
We'll do a tween info dot new and we can slowly open it.
So we could do like five seconds and then do an enum dot easing style of uh, we'll do linear and we're
going to want to change the key frame of this door equal to the exit door dot hinge dot c frame.
And we'll add a C frame angles.
We'll do zero on the x axis.
And then for the y axis we're going to do math dot rad and rotate it by around -110 degrees and then
zero on the z axis.
And that's all we need to do for this function.
So we can go back down into our start section two function.
We'll want to restore the power and then we'll want to enable our exit door.
From this point we can use our update GUI event and fire to all of the clients that they fulfilled,
an objective which was to restore the power.
So GUI actions enum dot objective fulfilled and then the fulfilled objective name is equal to restore
power.
And then we can use the update UI again and give them all a new objective.
So GUI actions, Nomad objective, and the name we could set for this objective would be like escape.
So we can go back up and create a new objective.
Call it escape.
And the text will set in here would be something like escape the basement.
We'll go back down, we'll give them this objective and then we'll give them the text which is in game
sections dot objectives, dot escape and then get the text.
After that, we're going to wait like one second, and then we're going to use the game comms event
and fire to all the clients to begin playing the sound or music that will play when they're trying to
escape.
So game comms enum on the client two client play sound and the sound is inside of the sound service.
Don ambience dot escape music and then play at point.
It's going to be equal to false.
So when it is time to escape the basement, we're going to be playing this.
Pretty basic and nice music.
And that's all we need to do for our start section to function.
It is over.
That means when we go back to our game service, where our start section two function was called, which
was right here, we can then go ahead and start executing functionality outside of it once we return
out of the function.
So now what we could do is we could create a new variable.
And we're going to call this ready for escape part.
By default we're going to set this to false.
And then we can scroll back down and set ready for escape part equal to true.
And what we're going to do is we're going to create a for loop starting at the index of 60, going all
the way down to I guess we'll do zero minus one each time.
And this is the loop we're going to do to give them a countdown to escape the basement.
So we'll use our update UI event and fire to all of the clients to do a GUI actions enum dot update
countdown.
And the number is going to be equal to the current index.
So this is going to be the timer for all the players to escape the basement.
And then once this loop is over, then we can have a function to teleport all of our players back to
the lobby or teleport the losing players back to the lobby, because when our winning players touch,
the part will automatically teleport them back, but any players that are left over or the losing players
will need to teleport them back to the lobby as well.
So we can scroll up and go ahead and create a private function, and we can call this function something
like teleport.
Losing players to lobby.
And what we would do is we would loop through every single player inside of the player service.
So whatever players are remaining inside of our game.
What we're going to do is we're going to ensure that they aren't an escaped players because we're going
to be doing something for the escape players.
So we'll have to create a table that keeps track of all the escaped players.
And inside of here we'll just insert the name of the player.
So.
Inside of our function.
We can check if inside of the escape players table this player is inside of it.
If they are an escape player.
If they are, then we're just going to continue looping.
Otherwise, what we could do is we could use our update UI event and fire to this particular player
and give them the action enum of outro frame.
So this is something we're going to have to fill out in our main UI handler.
And this means we're also going to have to give them a table containing a bunch of different data to
display on our outro frame.
So inside of our main guy handler on the client, when we are told to display an outro frame, what
we're going to do is we're going to get our outro frame and set the visibility equal to true.
And inside of this args table, we can have a bunch of different text passed to us.
So for example, inside of the outer frame.info label, we can set the text equal to whatever text is
passed from the server.
So we can have a key in there called like info text.
And then in the outro frame dot title label, we could add some text from the server as well.
So we could do args dot title text.
And then what we could also get passed to this function is the completed tasks that you know the player
finished.
So we could loop through every single, uh, task inside of a table like args dot completed tasks.
Because you remember inside of our tasks service, it can return back to us a table with a bunch of
different key value pairs, numbering the different tasks we completed so we could get that number value
and add it to a total.
So we could have a total here start at zero.
And then we will just add this number to the total.
And after we do that, inside of the outro frame, we have a stats label and we can set the text in
that equal to something like, we'll put a string here and we could say you had.
We'll put a directive percentage de dollars.
And percentage the tasks completed, so it'll tell us how much money we earned and how much tasks we
completed.
And then we can go ahead and format the string and pass the args.
And we could get like the amount of money we had.
So args dot money.
And then we could also pass the total number here of tasks we completed.
And then once we do that, our outer frame is still going to be invisible because it's currently transparent.
So we need to fade it in and we can use the fade element function, pass our outer frame.
And we're going to set the duration to one second.
And we want to fade it to be completely opaque.
And that means we're also going to have to fade in all of the different text labels inside of the outer
frame.
So we would get every single child inside of our outer frame, get children.
And we would fade the element of this particular child.
We'll do the same duration of one second and then zero for the transparency.
Now the problem is that this function if you remember, yields.
So instead we're going to have to spawn it in a new thread.
So task dot spawn this function.
And then we'll just pass all the other stuff along with it.
And then we can just basically copy this, do the same thing here, but instead we're passing the child
that is inside of our outro frame.
So this will fade all of the outro stuff onto our screen.
And then from this point, there's also a section in our outro frame where we'll have a section that
says teleporting you back to the lobby, and we'll do like teleporting back to lobby.
And then we could do dot dot, dot like a loading bar.
So we'll create a message here.
We'll just call it.
Teleporting you back to lobby.
And then inside of the outer frame dot loading text or I believe it's loading label.
We'll get the text in there and set it equal to this message.
We'll wait like point five seconds.
And then once we do that, we're going to have a loop that runs forever.
And what we're going to do is we're going to check if the outer frame dot loading label dot text is
equal to the message and concatenate it with the three dots.
And when it is, that means we're going to have to reset it back to the message.
So outro frame dot loading label dot text is equal to the message.
And then we can yield for something like 0.5 seconds.
And then after that.
We'll refer to the outer frame loading label dot text.
Set it equal to itself.
And then just concatenate it with a period.
And again we'll yield for 0.5 seconds.
So this loop will run forever.
Just filling out that loading bar for us.
So back inside of our game service, the things that we're going to have to pass here, first of all,
we're giving them the action of the outer frame and then inside of the table.
What we can pass in here is first the money that the player earns.
So that's going to be in the player's leader stats folder and get their money.
And then get the value of that money.
We could set the title text equal to something like you failed.
We'll set the info text equal to something like.
Unfortunately, you fail to win this time and we just give some encouraging words don't give up, try
again.
Something like that.
And we're also going to have to pass all of the completed tasks that this player, you know did.
So that means if you remember if we go back to our task service.
When our Bindable function is used.
If we scroll down here, we have our.
Where is it?
Task service.
The task service Bindable.
When that is invoked, we return back from this function, which gives us a table containing all of
the completed tasks.
So that means inside of our game service, we're going to have to make a reference to that remote function.
So we can scroll up.
We can have a section up here.
We'll call it Task Service Bindable.
And that's in the server storage dot events dot Bindesboll's.
Dot task service Bindable.
And that means we're also going to have to get the game comms enum for the server.
So we'll require from server script service, dot server, dot modules, dot enums, dot game communication
enum.
And then we can go back down.
And what we'll do is we'll create another key inside of here which represents the completed tasks.
And that's going to be equal to our task service buildable.
And we're going to invoke and pass the action using the uh, game comms enum for the server dot task
service.
And we're going to get completed tasks for player.
And if you remember, the player we need to pass here is going to be the player inside of this for loop.
So we'll just put the player inside of this table.
And we should be good to go there.
So once we do that for all the players, we're going to wait a random amount of time.
We could do like 10s.
That way we just have enough time for the players to read what's on their screen.
So we'll wait 10s and after those 10s, then we're just going to teleport every single player inside
of the game back to the lobby.
And that means we're going to have to use our teleport handler for doing this.
So let's go ahead and fill this service out in here, the only service we'll need is the teleport service.
We use game get service teleport service.
We'll create the table to represent this handler.
So teleport handler is equal to a table.
Return that at the end of this module script.
And then we're also going to make a reference to the place id enum, which is going to store all the
different place IDs.
So we'll require inside of the script the child is the place id enum.
And to fill this out we'll just grab one of these random enums like this one.
I'll copy all this, paste it inside of the place id enum.
But instead we want to delete this.
And we're going to want to make a key for our lobby or the ID to teleport the players back to the lobby.
So we can call this lobby, and we'll set it equal to a number.
And now to get the ID for our lobby, we can go to the view tab and open up our asset manager.
We can go to places in our game.
And then here is our lobby the horror game.
We can go copy the ID to clipboard and then store it inside of our table.
So back inside our place id enum, what we can do is we can have a function in here.
So teleport handler we can call it teleport player two.
And what this function will get past is a table containing all the players we wish to teleport, so
we can call it players, and this will be a table containing elements of the player data type.
And then we'll also get the ID that we want to teleport to.
Now, of course, just in case you know, a developer makes an error, we want to ensure that this place
ID actually exists within our place id enum.
So we could create a function to check that.
We could call it is id in enum.
And we would get passed an ID and all we'll do is we'll have a variable, we'll call it result, set
it to false by default.
And we're going to loop through every single enum and then value inside of our place id enum.
And we're going to check if the value is equal to this ID.
If it is, then we can set result equal to true.
Otherwise we're just going to return result which will either be true or false.
So we can check if this place ID passed to this function is not in this enum, and if it isn't, then
we're going to put out a warning message in the console.
So if not is id and enum, we'll pass the place ID.
If it's not in there, then we're going to put out a Warn statement and say something like incorrect
place ID given to teleport player to function, and then we can go ahead and return.
Otherwise the next thing we can do is we can use our teleport async function in the teleport service.
And we're going to use a p call on it.
So we'll get the success and the result from p call.
And the function we're going to p call is the teleport service dot teleport async.
Since this function uses a colon, that means we have to pass the teleport service itself as the first
argument, and then the second argument needs to be the id, which will pass as the place id.
And then the second argument needs to be the table containing all the players we wish to teleport,
which will be the players passed to this function.
If we were not successful in teleporting the players, then what we're going to do is we're going to
loop through every single player inside of our players table, and we're just going to kick them.
So player kick.
And we can give them a message like an error occurred.
When trying to teleport you back to the lobby, and we can go ahead and give them the error message
as well, using a directive.
And then we can go ahead and wrap this string in another set of parentheses, and then format this and
pass the result from our p call.
And then once that's done, we can just go ahead and return out of the function.
Otherwise, if we were successful in teleporting these players back to the lobby.
Then we're going to spawn a task delay function.
We'll wait 15 seconds.
And after that, any other player that is still somehow sitting in our game that was inside of this
player service, we're going to kick because somehow their teleport timed out.
So for every single player and players, what we'll do is we'll kick them and give them a message of
like teleport timed out, perfect.
And that's all we got to do for our teleport handler and our place ID enum, so we can go ahead and
close out of those.
And now back inside of the game service to teleport the losing players back to the lobby.
We're going to use our teleport handler, so we'll have to make a variable to it.
So up here we could have our teleport handler and we'll require it from service script service dot server,
dot modules dot teleport handler.
And then we'll also get the enum as well.
So place id enum will require from server script service.
That server dot modules, dot teleport handler, dot place id enum and then we can go back down.
Use our teleport handler and teleport player two.
We'll pass our player, so we'll use the player service and get all the players that are in the game.
And then the ID we're going to use is in the place id enum and pass the lobby.
Perfect.
So now we can go ahead and scroll back down, and we can go ahead and call this function after our for
loop has ended.
So we could call teleport losing players to lobby.
And now the next thing we can fill out is when our escape part gets touched.
So the first thing we want to check is if we're ready for this touch part.
So if not ready for our escape part, then we're just going to return.
If whatever touch this was not part of a character, so if not other part.
Dot parent find first child or which is a.
Humanoid, then we're going to go ahead and return, and we're going to have to get this other part.
We need to check if a player touched this so we can get the player from the player service players get
player from character.
Pass other parts.
Parent.
If there is no player, then we're just going to return and the next thing we need to check is if this
player already escaped.
So if inside of the escape players table, this player's name already has a key in there, then we're
just going to return.
Otherwise, inside of the escape players table, we can create a new key for this player player name.
And we'll just set it to something like true.
And then we can set an attribute on this player of escaped equal to true.
That way our AI doesn't try to target this player because they've escaped.
We're going to use the update UI event and fire to this particular player GUI actions enum dot objective
fulfilled and that is going to be the fulfilled objective name which is equal to escape.
From here.
We're also going to go ahead and get the completed tasks for this player.
So that means we'll get the result from our task service by double.
And we're going to invoke game comms, enum server, dot test service dot get completed tasks for player,
and the player is going to be the one inside of this function.
And actually I do remember that this invoke function returns two arguments.
One is a boolean and then the other is our result.
So that means back when we teleport the losing players to the lobby, we should actually get our tasks
outside of this.
So we'll copy this here.
Paste that here so we could call this, uh, we'll just call it completed tasks, and then we can pass
the completed tasks to this section right here.
Otherwise, this would be storing a boolean rather than the completed tasks.
And we'll make sure to close this out as well.
And then going back down.
Once we get the result from our task service Bindable invoke well, we can do is use the update UI event
again and actually pass the outer frame.
So this time we'll just basically copy what we've done here.
Paste that down here to complete a task is going to be equal to the result.
And instead, the message we can give them is that you escaped.
And then for the info text, if you would like, you could continue on expanding the story in the future.
So I've made this pretty easy where instead, when the players touch the escape part, you could teleport
them to a new section in your story if you'd like.
We're not going to be creating that new section.
I think our story is good the way it is, but if you would like to expand that story or add a second
section to the story, then you can give them some info text of like part two coming soon, whatever.
Because, you know, there's a lot of horror games like Judy that have different chapters in the game
that players could be able to play, and that's definitely something you could add into your horror
game later in the future.
Other than that, once we give them this information, we also want to award them a badge telling them
that they successfully escaped from our basement.
So that's where our badge handler is going to come into play.
And that means we're going to have to create a custom badge for our game, so we can go ahead and open
up our main story, and then we can go to file hit Game Settings.
And then we can go to monetization.
And inside of here is where we can create a new batch.
So let's go ahead and create one.
So now you should have this window opened up in your browser.
You can give the name for your badge and the description.
I'll just name this badge you escaped and say something like you successfully.
Escaped the basement after being chased or after being trapped or whatever.
We could do something like that, and then we can also upload an image for our badge as well, which
I'll do real quick.
So once you've uploaded your image, you've given a badge name and a description.
You can go ahead and hit preview.
Your image will show here, but since I just uploaded it, nothing is showing yet.
And then after that you can go ahead and purchase it for zero Robux so it's free.
After that, your badge has been successfully created and we can go back and hop into studio.
And back inside of studio, we can go ahead and refresh our badges.
And then here is our you escape the badge.
We can hit the three dots here and copy the ID, because we're going to need that in a moment.
But what we can do from this point is we can go ahead and start filling out our batch handler and our
batch enum.
So I'm going to go in here and again copy all of this, paste it inside of this enum.
And then I'm going to delete all of this.
And then windows has a neat feature.
If you're on Windows 11 where you can hit down the windows key and then V and it'll show you your clipboard
history where you can go ahead and grab your badge ID, but if you're not able to see your clipboard
history, then it's easy for you to just go back into the game settings and grab that badge ID again.
So in here we could create a key.
We can call it Escaped Badge.
And set it equal to the badge ID just like so, and then we can go ahead and start filling out our badge
handler.
So inside of this module script we're going to need the badge service.
So game get service badge service.
We'll create the table to represent this module script batch handler and return that at the end.
And then we can also make a reference to our badge enum, and we'll require it from script dot badge
enum.
We'll again have the same function to check whether or not an ID is inside of our enum, so we can call
it function is id an enum, and we will get past the badge id here.
Again.
We'll get our results.
We'll set it to false.
We'll loop through every single enum and value inside of our badge enum.
And if the value is equal to the badge ID passed to this function, then we can go ahead and set result
equal to true, and then return result at the very end of our function.
And then inside of this handler we can have a function to award a badge.
So badge handler award badge.
We would pass the player we would like to award the badge to.
And then we would pass the badge ID.
We will check if this badge ID is inside of our enum.
So if it is not, is id and enum, pass the badge ID.
Then we can warn, give out a message and correct a badge ID given to award badge function.
And then we'll just return.
Otherwise, again we're going to use our p call function on the award badge function.
So local success result is equal to p call.
And we'll use badge.
Service Award badge.
Since this function also uses a colon, the first argument we need to pass is the badge service itself,
and then we can pass the player user ID and then the badge ID.
If we were not successful in awarding the badge, then we'll just put a warning and say something like
unable to award badge.
We'll pass the ID of the badge here to player, and we could pass the name of the player here.
And then we can give out the error.
So we'll put another directive and then we can go ahead and format this.
The first thing we want to pass is the badge ID the second is the players name.
And then lastly is the result from our p call.
And that's all we need to do for our badge handler.
So inside of our game service we can go back up and create a new variable for the badge handler.
So local badge handler will require from server script service.
Dot server.
Dot modules.
Dot batch handler.
And then we're going to copy this and then get the badge enum.
Match handler and get the badge enum again, and then we can go back down.
And after we told the player that they have escaped, we can use our badge handler and award a badge
to this player.
And the badge ID is going to be from our badge enum, and we'll get the escaped badge.
After this, we can use task dot delay to spawn a function after like five seconds.
And the function we want to spawn is our teleport handler and we want to teleport a player two.
The first thing of course we need to pass is the teleport handler itself to fulfill the self variable.
Since this function uses a colon.
Then we could pass a table containing the player, and then the place we want to teleport this player
to is the place id enum dot lobby.
After this, we want to check how many players have escaped in our game.
So we'll create a number.
We'll set it to zero, and then we can loop through every single player inside of the player service.
Get players.
And what we want to do is we want to check if this player is inside of our escaped players table.
So we'll pass the player dot name.
If they are inside of there, then we can go ahead and increment our number.
And then after that, what we could do is we could check if our number is equal to the number of players
and the player service.
So get players.
If it is, then we can basically have a variable where we can say all the players have escaped.
And that way when this loop is happening up here, we can go ahead and stop the countdown from happening
so we can go up.
We can create a boolean, we'll call it all players escaped.
We'll set it to false by default.
Inside of this for loop we can check.
If all the players escape, then we can use our update guy event, fire to all the clients and do the
guy actions in the update countdown and set the number equal to zero.
That way the countdown stops for all the players, and then we can just go ahead and return out of this
function entirely, because we do not need to teleport any losing players back to the lobby, considering
all of the players have escaped.
And another important thing we need to ensure that we do in here is we actually yield for one second.
That way we're actually counting down for a total of 60s.
All right.
We got a lot of good work done in this lecture.
So now it's time for us to go ahead and test out whether or not we can escape from the basement so we
can go ahead and play test our story.
And when we get to the basement section, I'll go ahead and meet you there.
Okay.
Now we are inside of our basement, and what I'm going to do is I'm going to locate where the key giver
is for our breaker door.
So inside of the Krusty Krab basement, we're going to find the breaker room key giver.
So it's highlighted for us on the map.
And we can go ahead and try to find it, which it is over here.
So we're going to go ahead and grab this and head over to the door.
And when we open and unlock the door, that means the prompt that is inside of the breaker box in there
should be enabled.
So let's go ahead and test to see what happens.
We open that, there's our breaker panel and there should be a prompt.
Perfect.
We have an interact prompt.
If we hold down E.
Once we've triggered the prompt the light should turn back on.
We should get a countdown started and our skate music should start playing at the same time.
Our escape door should be opening and we should be able to touch the escape part.
So let's go ahead and see what happens.
So we hold down E, we hold down E and it eventually should trigger.
There we go.
We are told to escape the basement.
We have a countdown going.
As you can hear, our alarm is playing on the door.
So let's go ahead and run and hurry up before this timer reaches zero.
So we're running.
We're running trying to find the exit to the basement.
And there we go.
As you can see, our door is open.
The light is green, and there is this nice surface light projecting out of the part that is in this
door.
And if we go and touch it, we should get a thing displayed on our screen showing us what exactly we
completed.
Currently, I completed no tasks and I didn't get any money.
Should tell me zero and zero.
So let's go ahead and touch it and see what happens.
We did get our escape badge, which is great, but unfortunately we did get an error which was unable
to assign a property to text string.
Expected God to know our teleport system did work because we can't teleport in studio.
But let's go ahead and see what our problem is here.
So first off, in the main guy handler we have argument one missing or nil.
So that's on line 154.
So inside of our main guy handler on line 154 the fulfilled objective when we get.
This here.
Apparently the fulfilled objective name is probably nil again.
So if we go back to our game service.
And find out.
When we tell the player that they fulfilled an objective, perhaps we spelled something wrong.
And we did.
We did fulfilled object name instead of filled, fulfilled, objective name.
So we got to fix that.
And then the second area we had was on line 206 in our main guy handler.
So we'll scroll down to that.
And apparently args.info text is nil.
So that means when we get past information text I'll go ahead and look for that in here.
Info text.
Apparently this is nil and we pass it to the player, which is actually kind of interesting.
Because we pass the info text here and we also pass the info text here as well.
But it says we got nil.
Oh, and it looks like the problem is, for some reason, inside of here, we're passing.
A table with the player inside of it.
I have no idea why we're doing that inside of our Fhir client function.
Let's go ahead and get rid of that.
And then inside of the other info text section where for some reason doing the exact same thing.
So I'm going to delete that as well.
I'm not sure why that is in there.
But let me just double check that everything looks okay.
We get the money, we have the title text, we have the info text, and then we have the completed tasks.
Okay, that looks good.
We go to the other info text.
We have our money, the title text, the info text and then the completed tasks as well.
So that looks good.
Apparently we just had a minor syntactical error in our script, but other than that I think everything
should be working good now.
So let's go ahead and test out our game again.
All right.
We're almost done restoring the power here.
And there we go.
Our timer has started.
Let's go ahead and run over to the exit.
And let's see if we get any different errors.
This time when we try to teleport ourselves back.
So to run, we'll run.
Eventually we'll get there, make sure I'm.
I'm even getting lost.
But, uh, here it is.
Okay.
We run all the way to the exit.
And now when we touch this, we should get that guy showing up on our screen telling us what we got
done, and then we should get teleported back.
So we touch it.
There we go.
You escaped.
Part two.
Coming soon.
You have $0 and zero tasks completed, teleporting you back to the lobby.
And of course it's not working because we're in studio, but that means that it should be working when
we actually publish this game to Roblox.
So now the next thing I actually want to test is what happens if we don't reach that escape part in
time.
And look, we also got our teleport timed out as well.
Okay.
And this time I'm going to just sit here and let the timer reach zero.
And I want to see if we get the outro frame displayed on our screen where it tells us you failed, and
then we get teleported back to the lobby.
So let's go ahead and wait for this timer to run out and see what happens.
All right, our timer is almost over.
Three, two, one.
Let's see what happens.
Timers up and we did get an error.
So let's see what happened.
Attempt to index nil with number.
So we got attempt to index nil with number at the same spot twice.
So this was inside of our task service.
Let's go ahead and see what happened.
So on line 220 inside of the task service we're getting an error attempt to index nil with number.
And that's going to be right here.
So apparently args is nil.
And when we index it with one it doesn't like it.
And it's telling us we're attempting to index this which is nil with a number.
Why would that be a number.
Well it might be explained from our game service on line 77.
So let's go to that.
And inside of here when we use our task service Bindable and get the completed task for a player, it
looks like we actually forgot to actually pass the player in a table to our invoke function.
So that's exactly why it didn't work.
But now that we fixed that, let's go ahead and test this out one last time to see if it works or not.
Okay.
Our timer is almost up.
Let's go ahead and see what happens when we don't reach the exit door in time.
Got three.
Two, one.
Hopefully no errors.
There we go.
You failed.
Unfortunately, you failed to win this time.
Don't give up.
Try again and we should get teleported back to the lobby any second now.
At any second.
There we go.
Teleport fail due to an unexpected error because we can't teleport while we're in studio.
But it looks like everything we've scripted is working great.
And our teleport timed out as well, so that's also good to see.
So far everything is working well in our game and in the next lecture, I think it's time to get started
with scripting our AI.
Squidward.
I will see you there.